﻿using System;
using System.Collections.Generic;
using System.Text;
using StockTrader.BusinessService.DataContract.Mortgate;
using Mortgage.DDL;
using TCKQKL.FrontEnd.DataModel;
using StockTrader.FrontEnd.DataContract;
using MortgageMonitor.DDL;
using LoanMonitor.Business;
using StockTrader.FrontEnd.OrderTracker.Business;
using Mortgage.Enum;

namespace Mortgage.DAL
{
    public class StaticDataAccess
    {
        public static void InportLoadRate(LoanRateData item)
        {
            MortgageMornitorDAL dalClient = new MortgageMornitorDAL();
            dalClient.ImportLoadRate(item);
        }

        private static List<StocksUI> ConvertToStocksUI(List<TradingResultUI> list, int T, bool isCountSettlement)
        {
            List<StocksUI> holding = new List<StocksUI>();
            DALclient client = new DALclient();
            MortgageMornitorDAL dal = new MortgageMornitorDAL();
            decimal amplitude = 0;
            foreach (TradingResultUI result in list)
            {
                QuoteDataUI quote = client.getQuote(result.Symbol);

                if (quote != null)
                {
                    decimal rate = dal.getLoanRate(DateTime.Today, result.Symbol);
                    decimal refPrice = quote.Ref;
                    if (isCountSettlement)
                    {
                        amplitude = (quote.ExCenter.Equals("HOSE")) ? 0.05m : 0.07m;
                        refPrice = estimateFutureValue(quote.Ref, amplitude, T);
                    }
                    holding.Add(new StocksUI(quote.Symbol, result.SubQtty, refPrice, T, rate, quote.CompanyName));

                }
            }
            return holding;
        }
        private static List<OrderUI> MergeOrders(List<OrderUI> orders1, List<OrderUI> orders2)
        {
            try
            {
                List<OrderUI> mergedlist = new List<OrderUI>();
                mergedlist.AddRange(orders1);
                mergedlist.AddRange(orders2);
                return mergedlist;
            }
            catch (System.Exception e)
            {
                throw e;
            }
        }
        private static decimal estimateFutureValue(decimal Value, decimal amplitide, int T)
        {
            decimal price = Value;
            for (int i = 0; i < T; i++)
            {
                price = price * (1 - amplitide);
            }
            return price;
        }
        private static decimal getPortfolioValue(List<StocksUI> list, bool isDiscount)
        {
            decimal stockvalue = 0;

            DALclient client = new DALclient();
            foreach (StocksUI item in list)
            {
                QuoteDataUI quote = client.getQuote(item.Symbol);
                decimal amplitude = (quote.ExCenter.Equals("HOSE")) ? 0.05m : 0.07m;

                if (isDiscount)
                    stockvalue += item.Ref * item.Quantity * item.AllowRate * 1000;
                else
                    stockvalue += item.Ref * item.Quantity * 1000;
            }

            return stockvalue;
        }

        public static decimal getAccumulateValueByAccountNo(string AccountNo)
        {
            MortgageMornitorDAL client = new MortgageMornitorDAL();
            decimal AccumulateValue = 0;
            List<ContractData> cts = client.searchContract(string.Empty,
                                client.getCustomerIDByAccountNo(AccountNo),
                                DateTime.Today, DateTime.Today, 0, 0,
                                Convert.ToInt32(ContracType.All), ContractStatus.Open.ToString(),
                                AccountNo, string.Empty);

            foreach (ContractData ct in cts)
            {
                List<MortgageTrans> trans = client.getMortgageTransByCode(ct.ContractNo);
                foreach (MortgageTrans tran in trans)
                {
                    if (tran.TransType.Equals(Convert.ToInt32(TransType.WithDrawCash)))
                        AccumulateValue += tran.Credit;
                    if (tran.TransType.Equals(Convert.ToInt32(TransType.DepositCash)))
                        AccumulateValue -= tran.Debit;
                }
            }

            return AccumulateValue;
        }

        public static decimal getAccumulateValue()
        {
            MortgageMornitorDAL client = new MortgageMornitorDAL();
            decimal AccumulateValue = 0;
            List<ContractData> cts = client.searchContract(string.Empty,
                                string.Empty,
                                DateTime.Today, DateTime.Today, 0, 0,
                                Convert.ToInt32(ContracType.All), ContractStatus.Open.ToString(),
                                string.Empty, string.Empty);

            foreach (ContractData ct in cts)
            {
                List<MortgageTrans> trans = client.getMortgageTransByCode(ct.ContractNo);
                foreach (MortgageTrans tran in trans)
                {
                    if (tran.TransType.Equals(Convert.ToInt32(TransType.WithDrawCash)))
                        AccumulateValue += tran.Credit;
                    if (tran.TransType.Equals(Convert.ToInt32(TransType.DepositCash)))
                        AccumulateValue -= tran.Debit;
                }
            }

            return AccumulateValue;
        }

        public static AccountInfoUI GetAccountInfoUI(string AccountNo, bool isDiscount, bool isCountSettlement, bool isIntraday)
        {
            #region  Definitions

            AccountInfoUI AccInfo = new AccountInfoUI();
            AssetUI asset = new AssetUI();
            DALclient client = new DALclient();

            List<TransDataUI> BOSC_trans = new List<TransDataUI>();
            List<AccountDataUI> BOSC_stocks = new List<AccountDataUI>();
            List<BankDataUI> BOSC_cash = new List<BankDataUI>();
            List<TradingResultUI> BOSC_result = new List<TradingResultUI>();
            List<DateTime> backdate = new List<DateTime>();

            List<StocksUI> T0holding = new List<StocksUI>();
            List<StocksUI> T1holding = new List<StocksUI>();
            List<StocksUI> T2holding = new List<StocksUI>();
            List<StocksUI> T3holding = new List<StocksUI>();

            decimal T0BoughtStockValue = 0;
            decimal T1BoughtStockValue = 0;
            decimal T2BoughtStockValue = 0;
            decimal T3BoughtStockValue = 0;
            decimal PorfolioTradingStockValue = 0;
            decimal SoldAmount = 0;
            decimal BoughtAmount = 0;
            decimal NettingAmount = 0;
            decimal TradingAmount = 0;
            decimal BlockAmount = 0;

            Filter flt = new Filter();

            bool isClearing;
            #endregion

            try
            {
                AccInfo.Identity = new AccountUI(client.getCustomerInfo(AccountNo));
                AccInfo.CashHolding = new CashHoldingUI();

                #region  Share Objects
                decimal investorID = client.getAccountData(AccountNo).investorId;
                backdate = client.getBackDate();
                isClearing = client.isClearingDone();
                #endregion

                #region Cash
                BOSC_cash = client.getBankDataByInvestorId(investorID);

                #endregion

                #region Stocks

                #region T0

                #region Get all today orders
                List<OrderUI> AllCustomerOrders = new List<OrderUI>();
                List<OrderUI> CustormerOrders = new List<OrderUI>();
                List<OrderUI> HoOrders = new List<OrderUI>();
                List<OrderUI> HaOrders = new List<OrderUI>();

                HoOrders = client.getHoseOrders();
                HaOrders = client.getHastcOrders();
                AllCustomerOrders = MergeOrders(HaOrders, HoOrders);
                #endregion

                if (isClearing)
                    AllCustomerOrders = null;
                else
                    if (AllCustomerOrders.Count.Equals(0))
                        BOSC_result = client.getTradingResultHistory(
                            investorID, DateTime.Today, DateTime.Today, string.Empty, string.Empty,
                            "SELL", string.Empty, string.Empty, 0, 99999999, 0, 99999999);
                CustormerOrders = flt.ordersFilter(AllCustomerOrders, AccountNo, string.Empty, string.Empty);
                asset.T0Trading = CustormerOrders;

                if (isIntraday)
                {
                    SoldAmount = flt.getNettingAmount(CustormerOrders);
                    NettingAmount += SoldAmount;
                }

                foreach (OrderUI order in CustormerOrders)
                {
                    if (order.Side.Equals("MUA"))
                    {
                        QuoteDataUI quote = client.getQuote(order.Symbol);
                        if (isIntraday)
                        {
                            TradingAmount += (order.Volume - order.MVolume) * quote.Ref * 1000;
                            BlockAmount -= (order.Volume - order.MVolume) * quote.Ref * 1000;
                        }
                        decimal amplitude = (quote.ExCenter.Equals("HOSE")) ? 0.05m : 0.07m;
                        if (isDiscount)
                            T0BoughtStockValue += order.MVolume * estimateFutureValue(quote.Ref, amplitude, 3) * 1000;
                        else
                            T0BoughtStockValue += order.MVolume * estimateFutureValue(quote.Ref, amplitude, 0) * 1000;
                    }
                }
                BoughtAmount += flt.getSpentAmount(CustormerOrders);

                #endregion

                #region T0 trading results
                BOSC_stocks = client.getAccountByInvestorId(investorID);
                foreach (AccountDataUI stock in BOSC_stocks)
                {
                    long quantity = Convert.ToInt64(stock.tradingAmount);
                    QuoteDataUI quote = client.getQuote(stock.stockId);
                    MortgageMornitorDAL dal = new MortgageMornitorDAL();
                    decimal rate = dal.getLoanRate(DateTime.Today, stock.stockId);

                    if ((CustormerOrders.Count.Equals(0)) && (BOSC_result.Count > 0))
                    {
                        foreach (TradingResultUI order in BOSC_result)
                            if (order.Symbol.Equals(quote.Symbol) && order.Side.Equals("Bán"))
                                quantity += Convert.ToInt64(order.RootOrder.quantity);
                    }
                    else
                    {
                        if (isIntraday)
                            quantity += flt.getSellQttyBySymbol(CustormerOrders,
                                                              AccountNo, quote.Symbol);
                        else
                            quantity += flt.getRemainSellQttyBySymbol(CustormerOrders,
                                                                  AccountNo, quote.Symbol);
                    }
                    T0holding.Add(new StocksUI(quote.Symbol, quantity, quote.Ref, 0, rate, quote.CompanyName));
                }

                PorfolioTradingStockValue = getPortfolioValue(T0holding, isDiscount);
                #endregion

                if (!isClearing)
                {
                    T1holding = ConvertToStocksUI(client.getStockNettingInvestorId(
                                                        investorID, backdate[1]), 3, isCountSettlement);
                    T2holding = ConvertToStocksUI(client.getStockNettingInvestorId(
                                                        investorID, backdate[2]), 2, isCountSettlement);
                    T3holding = ConvertToStocksUI(client.getStockNettingInvestorId(
                                                        investorID, backdate[3]), 1, isCountSettlement);
                }
                else
                {
                    T1holding = ConvertToStocksUI(client.getStockNettingInvestorId(
                                                        investorID, backdate[0]), 3, isCountSettlement);
                    T2holding = ConvertToStocksUI(client.getStockNettingInvestorId(
                                                        investorID, backdate[1]), 2, isCountSettlement);
                    T3holding = ConvertToStocksUI(client.getStockNettingInvestorId(
                                                        investorID, backdate[2]), 1, isCountSettlement);

                }

                T1BoughtStockValue = getPortfolioValue(T1holding, isDiscount);
                T2BoughtStockValue = getPortfolioValue(T2holding, isDiscount);
                T3BoughtStockValue = getPortfolioValue(T3holding, isDiscount);

                #endregion

                AccInfo.CashHolding.StockTradingValue = PorfolioTradingStockValue + T0BoughtStockValue;
                AccInfo.CashHolding.StockWaitingValue = T1BoughtStockValue +
                                                        T2BoughtStockValue +
                                                        T3BoughtStockValue;

                AccInfo.CashHolding.CashTrading = BOSC_cash[0].tradingAmount + TradingAmount;
                AccInfo.CashHolding.CashWaiting = BOSC_cash[0].nettingAmount + NettingAmount;
                AccInfo.CashHolding.PreLoan = client.getPreLoanByInvestor(investorID);

                // Get accumulate loan
                AccInfo.CashHolding.AccumulateLoanValue = getAccumulateValueByAccountNo(AccountNo);


                AccInfo.StocksHolding = new List<StocksUI>();
                AccInfo.StocksHolding = MergeStockList(AccInfo.StocksHolding, T0holding);
                AccInfo.StocksHolding = MergeStockList(AccInfo.StocksHolding, T1holding);
                AccInfo.StocksHolding = MergeStockList(AccInfo.StocksHolding, T2holding);
                AccInfo.StocksHolding = MergeStockList(AccInfo.StocksHolding, T3holding);

                /*AccInfo.OpenContracts = client.searchContract(string.Empty, string.Empty,
                                                    DateTime.Now, DateTime.Now, 0, 0,
                                                    Convert.ToInt32(ContracType.Loan),
                                                    ContractStatus.Open.ToString(),
                                                    AccountNo, string.Empty);

                AccInfo.ClosedContracts = client.searchContract(string.Empty, string.Empty,
                                                    DateTime.Now, DateTime.Now, 0, 0,
                                                    Convert.ToInt32(ContracType.Loan),
                                                    ContractStatus.Closed.ToString(),
                                                    AccountNo, string.Empty);*/
                return AccInfo;
            }
            catch
            {
                return null;
            }
        }

        private static List<StocksUI> MergeStockList(List<StocksUI> list1, List<StocksUI> list2)
        {
            List<StocksUI> list = new List<StocksUI>();
            list.AddRange(list1);

            int stocknum = list.Count;
            if (list.Count.Equals(0))
            {
                for (int i = 0; i < list2.Count; i++)
                    if (list2[i].Quantity >= 100)
                        list.Add(list2[i]);
            }
            else
            {
                for (int i = 0; i < list2.Count; i++)
                {
                    bool notMatch = true;

                    for (int j = 0; j < list.Count; j++)
                        if (list2[i].IsEquals(list[j]))
                        {
                            list[j].Quantity += list2[i].Quantity;
                            notMatch = false;
                        }

                    if ((list2[i].Quantity >= 100) && notMatch)
                        list.Add(list2[i]);

                }
            }
            return list;
        }
    }
}
